package com.hmdp.utils;

import cn.hutool.core.lang.UUID;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;

import java.util.Collections;
import java.util.concurrent.TimeUnit;


/**
 * @author IT空门_门主
 * @date 2024/5/21
 */
@Slf4j
public class RedosLock implements ILock {
    private StringRedisTemplate stringRedisTemplate;

    private final static String KEY_PREFIX = "lock:";

    private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;
    static {
        UNLOCK_SCRIPT = new DefaultRedisScript<>();
        UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));
        UNLOCK_SCRIPT.setResultType(Long.class);
    }

    private String name;

    /**
     * redis 分布式锁
     * @param
     * @return
     */
    public RedosLock(StringRedisTemplate stringRedisTemplate, String name) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.name = name;
    }


    /**
     *  现在的代码 tyeLock ----> unlock
     *  存在着：原子性
     *  问题：幂等性是什么
     * @param timeoutSec
     * @return
     */
    @Override
    public boolean tyeLock(long timeoutSec) {
        //开启线程
        long threadId = Thread.currentThread().getId();
        //UUID+线程ID 保证唯一性
        String uuid = UUID.randomUUID().toString().replace("-","");
        log.info("线程ID:{}",uuid);
        String userThreadIdUuid=uuid+"-"+threadId;
        //IfAbsent 可以用于redis 分布式锁
        Boolean ifAbsent = stringRedisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, userThreadIdUuid, timeoutSec, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(ifAbsent);
    }

    /**
     * 释放锁
     */
    @Override
    public void unlock() {
        // 查询redis
        stringRedisTemplate.execute(
                UNLOCK_SCRIPT,
                Collections.singletonList(KEY_PREFIX + name),
                Thread.currentThread().getId()
                );
    }


    /**
     * 存在原子性问题-修改代码
     */
//    @Override
//    public void unlock() {
//        //查询redis
//        String  threadIdRedis= stringRedisTemplate.opsForValue().get(KEY_PREFIX + name);
//        //线程
//        long threadId = Thread.currentThread().getId();
//        if (!threadIdRedis.equals(threadId)){
//          return;
//        }
//        //删除redis，释放锁
//        log.info("删除redis锁-释放锁");
//        stringRedisTemplate.delete(KEY_PREFIX + name);
//    }
}
